package com.qdlc.p2p.biz.service.borrow.impl;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.qd.p2p.adapter.Response;
import com.qd.p2p.adapter.enums.ResponseStatus;
import com.qd.p2p.sina.pay.enums.IdentityType;
import com.qdlc.p2p.biz.processor.event.BorrowFullVerifyCollectNoticeEvent;
import com.qdlc.p2p.biz.service.AbstractCollectService;
import com.qdlc.p2p.biz.service.AccountService;
import com.qdlc.p2p.biz.service.RPCRequestService;
import com.qdlc.p2p.common.constant.BorrowTenderStatus;
import com.qdlc.p2p.common.constant.GeneralAccountType;
import com.qdlc.p2p.common.constant.Global;
import com.qdlc.p2p.common.constant.LogTplNid;
import com.qdlc.p2p.common.constant.NotifyUrl;
import com.qdlc.p2p.common.constant.Summary;
import com.qdlc.p2p.common.constant.TradeCode;
import com.qdlc.p2p.common.constant.TradeStatus;
import com.qdlc.p2p.common.core.ReturnResult;
import com.qdlc.p2p.common.core.queue.QueueHandlers;
import com.qdlc.p2p.common.util.CollectionUtils;
import com.qdlc.p2p.common.util.DataUtils;
import com.qdlc.p2p.common.util.MailUtil;
import com.qdlc.p2p.common.util.StringUtil;
import com.qdlc.p2p.dal.dao.BorrowTenderDao;
import com.qdlc.p2p.dal.dto.Borrow;
import com.qdlc.p2p.dal.dto.BorrowTender;
import com.qdlc.p2p.dal.dto.TppTradeLog;
import com.qdlc.p2p.dal.dto.User;
import com.qdlc.p2p.dal.model.BorrowModel;
import com.qdlc.p2p.dal.util.UserUtils;

/**
 * 满标复审 代收服务类
 *
 * @author Kaiju Zhao
 * @date 2016-03-09
 * @version 1.1.0.0
 */
@Service("borrowFullVerifyCollectService")
public class BorrowFullVerifyCollectServiceImpl extends AbstractCollectService {

	private final static String BUSINESS_NAME = "满标复审或撤回标代收-";

	// 借款标Model
	private ThreadLocal<BorrowModel> borrowModelLocal = new ThreadLocal<BorrowModel>();

	// 交易日志记录
	private ThreadLocal<TppTradeLog> tppTradeLogLocal = new ThreadLocal<TppTradeLog>();

	@Resource
	private BorrowTenderDao borrowTenderDao;

	@Resource
	private AccountService accountService;

	@Resource
	@Qualifier("bfRPCRequestService")
	private RPCRequestService<Response, TppTradeLog> rpcRequestService;

	@Override
	public String getCallBackUrl() {
		return WEB_URL.concat(NotifyUrl.BORROW_REFUND_COLLECT_URL).concat(".html");
	}

	@Override
	public String getBusinessName() {
		return BUSINESS_NAME;
	}

	@Override
	public void analyzePars(Object... pars) {
		if (null == pars
				|| 1 !=  pars.length) {
			throw new IllegalArgumentException("参数个数不正确!");
		}

		if (null == pars[0]) {
			throw new IllegalArgumentException("参数不能为null!");
		}

		boolean isBorrowModel = pars[0] instanceof BorrowModel;
		boolean isTppTradeLog = pars[0] instanceof TppTradeLog;

		if (!isBorrowModel && !isTppTradeLog) {
			throw new IllegalArgumentException("参数类型不正确!");
		}

		if (isBorrowModel) {
			borrowModelLocal.set((BorrowModel) pars[0]);
		} else if (isTppTradeLog) {
			tppTradeLogLocal.set((TppTradeLog) pars[0]);
		}
	}

	@Override
	public List<TppTradeLog> createOrders(Object... pars) {
		analyzePars(pars);

		BorrowModel borrowModel = borrowModelLocal.get();

		// 第三方任务处理列表
		List<TppTradeLog> tppTradeLogList = new ArrayList<TppTradeLog>();
		long borrowId = borrowModel.getId();
		List<BorrowTender> borrowTenderList = borrowTenderDao.find(borrowModel.getId(), BorrowTenderStatus.PROCESSED);
		User user = borrowModel.getUser();
		long borrowUserId = user.getUserId();
		String tppUserCustId = UserUtils.getUserTppCustId(borrowUserId);
		if (CollectionUtils.isNotNullOrEmpty(borrowTenderList)) {
			for (BorrowTender tender : borrowTenderList) {
				User tenderUser = tender.getUser();
				double transAmount = tender.getAccount();
				long tenderUserId = tenderUser.getUserId();

				// 封装第三方业务处理对象
				String tenderBilNo = tender.getTenderBilNo();
				if (StringUtil.isNotBlank(tenderBilNo)) {
					String toTppUserCustId = UserUtils.getUserTppCustId(tenderUserId);

					Map<String, Object> memo = new HashMap<String, Object>();
					memo.put("borrowId", borrowId);
					memo.put("tenderId", tender.getId());
					memo.put("borrowUserId", borrowUserId);
					memo.put("tenderUserId", tenderUserId);
					memo.put("tenderBilNo", tenderBilNo);

					Global.setTransfer("memo", memo);
					Global.setTransfer("tppUserCustId", tppUserCustId);
					Global.setTransfer("toTppUserCustId", toTppUserCustId);
					Global.setTransfer("borrowId", borrowId);
					Global.setTransfer("transAmount", transAmount);
					tppTradeLogList.add(createOrder(pars));
				}
			}
		}
		return tppTradeLogList;
	}

	@Override
	public ReturnResult requestOrder(TppTradeLog tppTradeLog) {
		Response response = null;
		if (!isSuspend(tppTradeLog.getTradeType())) {
			response = rpcRequestService.flowBorrowRefundRequest(tppTradeLog);
		}

		// 未知状态通知 交由消息队列处理
		if (null == response || ResponseStatus.UN_KNOW == response.getStatus()) {
			notice(tppTradeLog, TradeStatus.TRADE_STATUS_UN_KNOW);
			return new ReturnResult(true, "系统处理中!");
		}

		ResponseStatus status = response.getStatus();

		if (ResponseStatus.SUCCESS == status) {
			tppTradeLog.setRemark(getBusinessName().concat("提交成功"));
			tppTradeService.update(tppTradeLog);

			// 成功通知
			notice(tppTradeLog, TradeStatus.TRADE_STATUS_FINISHED);
			requestOrderSuccess(tppTradeLog); // 请求成功处理
		} else if (ResponseStatus.FAILURE == status) {
			String message = response == null ? "RPC调用失败" : MessageFormat.format("{0}代收失败!responseCode:{1} responseMsg:{2}",
					getBusinessName(), response.getResponseCode(), response.getResponseMsg());
			String responseMessage = response == null ? "RPC调用失败" : response.getResponseMsg();
			logger.info(message);

			// 置为废单
			tppTradeLog.setTradeStatus(TradeStatus.TRADE_STATUS_INVALID.getStatus());
			tppTradeLog.setRemark(getBusinessName().concat("提交失败-" + responseMessage));
			tppTradeService.update(tppTradeLog);

			requestOrderFail(tppTradeLog); // 请求失败处理
			return new ReturnResult(true, message);
		}
		return ReturnResult.SUCCESS;
	}

	@Override
	public TppTradeLog getTppTradeLog() {
		Map<String, Object> memo = (Map<String, Object>) Global.getTransfer().get("memo");
		String tppUserCustId = StringUtil.isNull(Global.getTransfer().get("tppUserCustId")) ;
		String toTppUserCustId = StringUtil.isNull(Global.getTransfer().get("toTppUserCustId")) ;
		long borrowId = DataUtils.toLong(Global.getTransfer().get("borrowId"));
		double transAmount = DataUtils.toDouble(Global.getTransfer().get("transAmount"));

		// 创建代收订单
		TppTradeLog tppTradeLog = new TppTradeLog();
		tppTradeLog.setTppUserCustId(tppUserCustId); // 标所属用户标识
		tppTradeLog.setToTppUserCustId(toTppUserCustId); // 投标用户标识
		tppTradeLog.setBorrowId(borrowId); // 标ID
		tppTradeLog.setMoney(transAmount); // 退款金额
		tppTradeLog.setIdentityType(IdentityType.UID.name());
		tppTradeLog.setBorrowRepaymentId(GeneralAccountType.INVESTOR);
		tppTradeLog.setMemo(JSON.toJSONString(memo)); // 备注信息
		tppTradeLog.setServiceType(Summary.REFUND.getSummaryType());
		tppTradeLog.setTradeType(TradeCode.C1007.toString());

		return tppTradeLog;
	}

	@Override
	public void tradeFinish(TppTradeLog tppTradeLog, String depositStatus, double tradeAmount) {
		super.tradeFinishForStatus(tppTradeLog, depositStatus, tradeAmount);

		JSONObject memo = JSON.parseObject(tppTradeLog.getMemo());
		BorrowTender borrowTender = borrowTenderDao.getTenderByBillNo(memo.getString("tenderBilNo"));
		Borrow borrow = borrowTender.getBorrow();

		double transAmount = borrowTender.getAccount();
		Global.setTransfer(LogTplNid.LOG_TPL_KEY, LogTplNid.UNFREEZE_NO_PASS);
		Global.setTransfer("web_url", WEB_URL);
		Global.setTransfer("borrow", borrow);
		Global.setTransfer("money", transAmount);
		accountService.unFreeze(borrowTender.getUser().getUserId(), borrow.getUser().getUserId(), transAmount);

		borrowTender.setStatus(BorrowTenderStatus.FAIL);
		borrowTenderDao.save(borrowTender);
	}

	@Override
	public void tradeSuccess(TppTradeLog tppTradeLog, String depositStatus) {
		super.tradeSuccessForStatus(tppTradeLog, depositStatus);
	}

	@Override
	public void tradeFail(TppTradeLog tppTradeLog, String depositStatus) {
		super.tradeFailForStatus(tppTradeLog, depositStatus);
		// 回调失败
		requestOrderFail(tppTradeLog);
	}

	@Override
	public void requestOrderFail(TppTradeLog tppTradeLog) {
		String message = BUSINESS_NAME + "交易失败";
		MailUtil.sendMail(message, message + " ,交易记录(TppTradeLog)中的订单号orderNo: " + tppTradeLog.getOrderNo(), "");
	}

	/**
	 * 发送流标退款通知 交由队列来执行
	 */
	private void notice(TppTradeLog tppTradeLog, TradeStatus tradeStatus) {
		BorrowFullVerifyCollectNoticeEvent noticeEvent = new BorrowFullVerifyCollectNoticeEvent();
		noticeEvent.setClientIp(Global.getIP());
		noticeEvent.setTradeStatus(tradeStatus);
		noticeEvent.setTppTradeLog(tppTradeLog);
		noticeEvent.setOutOrderNo(tppTradeLog.getOrderNo());
		noticeEvent.setDepositAmount(tppTradeLog.getMoney());
		QueueHandlers.put(noticeEvent);
	}
}
